﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace JXT.PrimaryKey.Batman.Reflection
{
    /// <summary>
    /// 高级Lambda属性对象
    /// </summary>
    public sealed class LambdaPropertyInfo
    {
        /// <summary>
        /// 对应属性
        /// </summary>
        public PropertyInfo Property { get; private set; }

        private Func<object, object[], object> getInvoker;
        private Func<object, object[], object> setInvoker;

        private readonly Func<Func<object, object[], object>> getInvokerCallable;
        private readonly Func<Func<object, object[], object>> setInvokerCallable;

        /// <summary>
        /// 属性名
        /// </summary>
        public string Name { get { return Property.Name; } }

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="property">属性对象</param>
        internal LambdaPropertyInfo(PropertyInfo property)
        {
            Property=property;
            getInvokerCallable = () => {
                if (getInvoker == null)
                    getInvoker = property.GetGetMethod(true).GetLambdaInvoker();
                return getInvoker;
            };
            setInvokerCallable = () =>
            {
                if (setInvoker == null)
                    setInvoker = property.GetSetMethod(true).GetLambdaInvoker();
                return setInvoker;
            };
        }

        /// <summary>
        /// 设置属性值
        /// </summary>
        /// <param name="instanse">对象</param>
        /// <param name="value">值</param>
        public void Set(object instanse, object value)
        {
            setInvokerCallable()(instanse, new object[] { value });
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="instanse">对象</param>
        /// <returns>获取值</returns>
        public object Get(object instanse)
        {
            return getInvokerCallable()(instanse, null);
        }
    }
}
